//---------------------------------------------------------------------
//
//---------------------------------------------------------------------
import java.util.*;

class SymbolTable
{
	private Stack<Scope> m_stkScopes;
	private int m_nLevel;
	private Scope m_scopeGlobal;
	private FuncSTO m_func = null;
	
	// Check 13: for structdef
	private Scope structScope; 
    
	//----------------------------------------------------------------
	//
	//----------------------------------------------------------------
	public SymbolTable()
	{
		m_nLevel = 0;
		m_stkScopes = new Stack<Scope>();
		m_scopeGlobal = null;
	}

	//----------------------------------------------------------------
	//
	//----------------------------------------------------------------
	public void insert(STO sto)
	{
		Scope scope = m_stkScopes.peek();
		scope.InsertLocal(sto);
	}

	//----------------------------------------------------------------
	//
	//----------------------------------------------------------------
	public STO accessGlobal(String strName)
	{
		return m_scopeGlobal.access(strName);
	}

	//----------------------------------------------------------------
	//
	//----------------------------------------------------------------
	public STO accessLocal(String strName)
	{
		Scope scope = m_stkScopes.peek();
		return scope.accessLocal(strName);
	}

	//----------------------------------------------------------------
	//
	//----------------------------------------------------------------
	public STO access(String strName)
	{
		Stack<Scope> stk = new Stack<Scope>();
		Scope scope;
		STO stoReturn = null;	
		
		/******** PHASE 0.2.1: Changed FIFO into LIFO using a Stack *********/
		for (Enumeration<Scope> e = m_stkScopes.elements(); e.hasMoreElements();)
		{
			scope = e.nextElement();
			stk.push(scope) ;
		}
		
		while (!stk.empty()){
			scope = stk.pop() ;
			if ((stoReturn = scope.access(strName)) != null)
				return stoReturn;
		}

		return null;
	}

	//----------------------------------------------------------------
	//
	//----------------------------------------------------------------
	public void openScope()
	{
		Scope scope = new Scope();
		// The first scope created will be the global scope.
		if (m_scopeGlobal == null)
			m_scopeGlobal = scope;

		m_stkScopes.push(scope);
		m_nLevel++;
	}

	//----------------------------------------------------------------
	//
	//----------------------------------------------------------------
	public void closeScope()
	{
		m_stkScopes.pop();
		m_nLevel--;
	}

	//----------------------------------------------------------------
	//
	//----------------------------------------------------------------
	public int getLevel()
	{
		return m_nLevel;
	}
	
	public void setScopeReturn() {
		m_stkScopes.get(getLevel()-1).setReturnStmt(true);
	}
	
	public boolean getCurrentScopeReturn() {
		if(m_stkScopes.get(getLevel()-1).hasReturnStmt()) {
			return true;
		}
		return false;
	}

	public Scope getCurrentScope() {
		return m_stkScopes.peek();
	}
	
	//---------------------------------------------------------------
	//	This is the function currently being parsed.
	//----------------------------------------------------------------
	public FuncSTO getFunc() { return m_func; }
	public void setFunc(FuncSTO sto) { m_func = sto; }

	public Scope getStructScope() {
		return structScope;
	}

	public void setStructScope(Scope structScope) {
		this.structScope = structScope;
	}
	
	public Scope getM_scopeGlobal() {
		return m_scopeGlobal;
	}

	public void setM_scopeGlobal(Scope m_scopeGlobal) {
		this.m_scopeGlobal = m_scopeGlobal;
	}

	public STO accessStructScope(String strName){
		Stack<Scope> stk = new Stack<Scope>();
		Scope scope;
		STO stoReturn = null;	
		
		/******** PHASE 0.2.1: Changed FIFO into LIFO using a Stack *********/
		for (Enumeration<Scope> e = m_stkScopes.elements(); e.hasMoreElements();)
		{
			scope = e.nextElement();
			stk.push(scope) ;
		}
		
		while (!stk.empty()){
			scope = stk.pop() ;
			if ( scope == getM_scopeGlobal() ) {
				break ;
			}
			if ((stoReturn = scope.access(strName)) != null)
				return stoReturn;
		}

		return null;
	}
}
